﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;



namespace Design
{

    //深拷贝：可以通过序列化的方式。抽象类及具体类都必须标注为可序列化的[Serializable]
    // http://www.cnblogs.com/knowledgesea/p/3930009.html
    //http://www.cnblogs.com/Terrylee/archive/2006/01/16/317896.html

    //原型模式
    [Serializable]
    public abstract class ColorPrototype
    {
        public abstract ColorPrototype Clone(bool Deep);
    }

    [Serializable]
    public class ConcteteColorPrototype : ColorPrototype
    {
        private int _red, _green, _blue;
        public string _name;
        public ConcteteColorPrototype(int red, int green, int blue, string name)
        {
            this._red = red;
            this._green = green;
            this._blue = blue;
            this._name = name;
        }

        public int Red
        {
            get { return _red; }
            set { _red = value; }
        }
        public int Green
        {
            get { return _green; }
            set { _green = value; }
        }
        public int Blue
        {
            get { return _blue; }
            set { _blue = value; }
        }
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public override ColorPrototype Clone(bool Deep)
        {
            if (Deep)
            {
                return CreateDeepCopy();
            }
            else
            {
                //实现浅拷贝
                return (ColorPrototype)this.MemberwiseClone();
            }
        }

        /// <summary>
        /// 实现深拷贝
        /// </summary>
        /// <returns></returns>
        public ColorPrototype CreateDeepCopy()
        {
            ColorPrototype colorPrototype;
            MemoryStream memory = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(memory,this);
            memory.Position = 0;
            colorPrototype = (ColorPrototype)formatter.Deserialize(memory);
            return colorPrototype;
        }

        public ConcteteColorPrototype Create(int red, int green, int blue, string name)
        {
            return new ConcteteColorPrototype(red,green,blue,name);
        }
        public void Display(string _colorname)
        {
            Console.WriteLine("{0}'s RGB Values are:{1},{2},{3},{4}", _colorname, _red, _green, _blue, _name);
        }
    }

    public class ColorManager
    {
        Hashtable colors = new Hashtable();
        public ColorPrototype this[string name]
        {
            set
            {
                colors.Add(name, value);
            }
            get
            {
                return (ColorPrototype)colors[name];
            }
        }
    }

    public class PrototypeTest
    {

        /// <summary>
        /// 原型模式 测试
        /// </summary>
        public void Prototype_Test()
        {
            ColorManager colormanager = new ColorManager();
            //初始化颜色
            colormanager["red"] = new ConcteteColorPrototype(255, 0, 0, "red");
            colormanager["green"] = new ConcteteColorPrototype(0, 255, 0, "green");
            colormanager["blue"] = new ConcteteColorPrototype(0, 0, 255, "blue");
            colormanager["angry"] = new ConcteteColorPrototype(255, 54, 0, "angry");
            colormanager["peace"] = new ConcteteColorPrototype(128, 211, 128, "peace");
            colormanager["flame"] = new ConcteteColorPrototype(211, 34, 20, "flame");

            //使用颜色
            string colorName = "red";
            ConcteteColorPrototype c1 = (ConcteteColorPrototype)colormanager[colorName];
            c1.Display(colorName);

            colorName = "peace";
            ConcteteColorPrototype c2 = (ConcteteColorPrototype)colormanager[colorName].Clone(false);
            c2.Display(colorName);

            colorName = "flame";
            ConcteteColorPrototype c3 = (ConcteteColorPrototype)colormanager[colorName].Clone(false);
            c3.Display(colorName);
              
        }
    }



    //------------------------------------------------
    /*
     *     
     * 下面的例子 证明：
     *   浅拷贝：只复制对象的基本类型，对象类型仍然属于原来的引用； 浅拷贝 更改被复制对象的属性值，原对象的属性也会更改 (浅拷贝原对象或拷贝对象 的对象类型发生更改，原对象和拷贝对象都会发生改变)
     *   深拷贝：完全是新对象产生的
     * **/


    //选答题 类
    public class SelectTest
    {
        //你的年龄
        private string age;
        public string Age
        {
            get { return age; }
            set { age = value; }
        }
    }

    /// <summary>
    /// 面试题
    /// </summary>
    public interface IinterView
    {
        IinterView Clone();

        //知道设计模式
        string KnowDesign { get; set; }


        //有几种设计模式
        string SeveralDesign { get; set; }

        /// <summary>
        /// 你知道哪些
        /// </summary>
        string youKnow { get; set; }

        //附加题
        SelectTest selTest { get; set; }
    }

    public class InterView : IinterView
    {

        private string one;
        private string two;
        private string three;
        private SelectTest other = new SelectTest();
        public IinterView Clone()
        {
            //克隆当前类
            return (IinterView)this.MemberwiseClone();
        }

        public string KnowDesign
        {
            get
            {
                return this.one;
            }
            set
            {
                this.one = value;
            }
        }

        public string SeveralDesign
        {
            get
            {
                return this.two;
            }
            set
            {
                this.two = value;
            }
        }

        public string youKnow
        {
            get
            {
                return this.three;
            }
            set
            {
                this.three = value;
            }
        }

        public SelectTest selTest
        {
            get
            {
                return this.other;
            }
            set
            {
                this.other = value;
            }
        }
    }

    public class InterTest
    {

        public void Inter_Test()
        {
            IinterView testOld = new InterView();

            IinterView test1 = testOld.Clone();

            testOld.KnowDesign = "20";
            testOld.selTest.Age = "20";

            test1.KnowDesign = "clone :21";
            test1.selTest.Age = "clone: 21";

            Console.WriteLine("testOld:"+testOld.KnowDesign+"/"+testOld.selTest.Age);
            Console.WriteLine("test1:" + test1.KnowDesign + "/" + test1.selTest.Age);
            
        }
    }
}
